package com.gridpower.spreadsheet.client.widgets;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.gridpower.spreadsheet.client.models.AppModel;
import com.gridpower.spreadsheet.client.models.DocModel;
import com.gridpower.spreadsheet.client.models.UIMouseModel;
import com.gridpower.spreadsheet.client.models.UISelectModel;
import com.gridpower.spreadsheet.client.models.AppModel.CellSelection;
/**
 * refactor needed, GridPart and HoriRuler have something in
 * common.
 * render canvas or move canvas
 * @author 438
 *!!!:no need to draw fixed long vert bar
 */
public class HoriRuler {
	int viewableLeft = 0; // x, if the seperator has effect
	int height = 30;
	int width = 200;
	int firstColWidth = 30;
	int seperatorWidth = 8;
	
	private AbsolutePanel heldPanel = new AbsolutePanel() {
		@Override
		public void onBrowserEvent(Event evt) {
			//System.out.println("widget"+DOM.eventGetType(evt));
			handleBrowserEvent(evt);
		}
	};
	private GWTCanvas gridCanvas = new GWTCanvas();
	private TextLayer txtCanvas = new TextLayer();
	protected GWTCanvas decorateCanvas = new GWTCanvas();
	
	
	public HoriRuler() {
		heldPanel.sinkEvents( DOM.getEventsSunk(heldPanel.getElement())
				|Event.MOUSEEVENTS | Event.ONCLICK);
		heldPanel.setHeight(height+"px");
		heldPanel.add(gridCanvas, 0, 0);
		heldPanel.add(txtCanvas, 0, 0);
		/*
		heldPanel.add(decorateCanvas);
		DOM.setStyleAttribute(decorateCanvas.getElement(),
				 "opacity", "0.5");
		DOM.setStyleAttribute(decorateCanvas.getElement(),
				"filter",
				"Alpha(opacity=" + "50" + ")");
		decorateCanvas.setBackgroundColor(Color.BLACK);
		decorateCanvas.setLineWidth(2);
		decorateCanvas.setStrokeStyle(Color.GREEN);
		decorateCanvas.resize(0, 0);
		decorateCanvas.setVisible(false);
		*/
	}
	public void render() {
		// draw two hori lines
		gridCanvas.clear();
		gridCanvas.setGlobalCompositeOperation(GWTCanvas.DESTINATION_OVER);
	    gridCanvas.setLineWidth(1);
	    gridCanvas.setBackgroundColor(Color.LIGHTGREY);
	    gridCanvas.beginPath();
	    gridCanvas.moveTo(0, 0);
	    gridCanvas.lineTo(width, 0);
	    gridCanvas.moveTo(0, height);
	    gridCanvas.lineTo(width, height);
		// draw vert lines to seperator
	    DocModel docModel = AppModel.getInstance().getCurrentDoc();
	    int fixed = docModel.getFixedColCount();
	    ArrayList colStarts = UIUtil.getAppView().getColStarts();
	    Iterator itr = colStarts.iterator();
	    int i = 0;
	    int x = firstColWidth;
	    int base = firstColWidth;
	    
	    gridCanvas.moveTo(0, 0); gridCanvas.lineTo(0, height);
	    gridCanvas.moveTo(x, 0); gridCanvas.lineTo(x, height);
	    while (itr.hasNext()) {
	    	x = base + (Integer)itr.next();
	    	gridCanvas.moveTo(x, 0); gridCanvas.lineTo(x, height);
	    	i++;
	    	if (i == fixed+1)
	    		break;
	    }
		// draw the seperator
	    int mark = x;
	    x+=seperatorWidth;
	    
	    // base += seperatorWidth;
	    base -= viewableLeft;
	    gridCanvas.moveTo(x, 0); gridCanvas.lineTo(x, height);
	    //	  draw vert lines from the seperator
	    while (itr.hasNext()) {
	    	x = base + (Integer)itr.next();
	    	if (x >= mark && x <= width) {
	    		gridCanvas.moveTo(x, 0); gridCanvas.lineTo(x, height);
	    	}
	    }
		gridCanvas.stroke();
		
		// render the text!
		// render to the fixed
		txtCanvas.clearElems();
		String str = "";
		base = firstColWidth;
		for (i = 0; i < fixed; ++i) {
			int x1 = (Integer)colStarts.get(i);
			int y1 = 0;
			int wid = (Integer)colStarts.get(i+1)-x1;
			int hgt = height;
			Element div = UIUtil.getAppView().getHoriRulerTextElement(i);
			str = "";
			str += (char)('A'+i);
			txtCanvas.drawTextInElement(div, x1+base, y1,
					wid, hgt, str, null, null, "0", null);
			// render the txt
		}
		
		base -= viewableLeft;
		int critX = (Integer)colStarts.get(fixed);
		for (; i < colStarts.size() - 1; ++i) {
			int x1 = (Integer)colStarts.get(i);
			int y1 = 0;
			int hgt = height;
			int nextX = (Integer)colStarts.get(i+1);
			int wid =  nextX -x1;
			str = "";
			str += (char)('A'+i);
			if (nextX+base >= critX && nextX+base <= width) {
				Element div = UIUtil.getAppView().getHoriRulerTextElement(i);
				txtCanvas.drawTextInElement(div, x1+base, y1,
						wid, hgt, str, null, null, "0", null);
			}
		}
	}
	/**
	 * handle browser event
	 * @return
	 */
	public void handleBrowserEvent(Event event) {
		// ScrollPanel
		// FocusPanel, Focus
		//System.out.println(DOM.eventGetType(event));
		//GWT.log("event", null);
		//DOM.eventCancelBubble(event, true);
		UIMouseModel mouseModel = AppModel.getInstance().getMouseModel();

		 switch (DOM.eventGetType(event)) {
	      case Event.ONMOUSEDOWN:
	      {
	    	  Element senderElem = heldPanel.getElement();
	    	  int x = DOM.eventGetClientX(event)
	    	  	- DOM.getAbsoluteLeft(senderElem)
	    	  	//+ DOM.getElementPropertyInt(senderElem, "scrollLeft")
	    	  	+ Window.getScrollLeft();
	    	  UISelectModel selectModel = AppModel.getInstance().getSelectModel();
	    	  DocModel docModel =AppModel.getInstance().getCurrentDoc();

	    	  ArrayList colStarts = UIUtil.getAppView().getColStarts();
	    	  int fixed = docModel.getFixedColCount();
	    	  if (x > (Integer)colStarts.get(fixed)) {
	    		x += viewableLeft;  
	    	  } 
	    	  int col = GridPart.binarySearch(colStarts, 0, colStarts.size(), x, 0);
	    	  mouseModel.setObjectMouseDownOn(UIMouseModel.OBJ_HORIRULER);
	    	  mouseModel.setMouseDown(true);
	    	  mouseModel.setDownCol(col);//must
	    	  selectModel.setRowColSelection(true);
	    	  CellSelection sel = selectModel.getCurrentSelect();
	    	  sel.rowStart = 0; sel.rowEnd =docModel.getRowCount()-1;
	    	  sel.colStart = sel.colEnd = col;
	    	  
	    	  break;  
	      }
	      case Event.ONMOUSEUP:
	      {
	    	  // set mouse down to false
	    	  mouseModel.setMouseDown(false);

	    	  if (mouseModel.getObjectMouseDownOn().equals(UIMouseModel.OBJ_HORIRULER)) {
	    			  //&& mouseModel.isMouseDown() == true) {
	    		  setCurrentSelect(event);
	    	  }
	    	  break;
	      }
	      case Event.ONMOUSEMOVE:
	      {
	    	  if (mouseModel.getObjectMouseDownOn().equals(UIMouseModel.OBJ_HORIRULER)
	    			  && mouseModel.isMouseDown() == true) {
	    		  setCurrentSelect(event);
	    	  }
	    	  break;
	      }
		 }
	}
	public int getHeight() {
		return height;
	}
	public int getViewableLeft() {
		return viewableLeft;
	}
	public int getWidth() {
		return width;
	}
	
	
	public void setHeight(int height) {
		this.height = height;
		heldPanel.setHeight(height+"px");
		gridCanvas.resize(width, height);
		txtCanvas.setSize(Integer.toString(width) + "px",
				Integer.toString(height)+"px");
		//render();
	}
	public void setViewableLeft(int viewableLeft) {
		this.viewableLeft = viewableLeft;
		//render();
	}
	public void setWidth(int width) {
		this.width = width;
		heldPanel.setWidth(width+"px");
		gridCanvas.resize(width, height);
		txtCanvas.setSize(Integer.toString(width) + "px",
				Integer.toString(height)+"px");
		//render();
	}
	public AbsolutePanel getHeldPanel() {
		return heldPanel;
	}
	public void setHeldPanel(AbsolutePanel heldPanel) {
		this.heldPanel = heldPanel;
	}

	private void setCurrentSelect(Event event) {
		UISelectModel selectModel = AppModel.getInstance().getSelectModel();
		DocModel docModel =AppModel.getInstance().getCurrentDoc();
		UIMouseModel mouseModel = AppModel.getInstance().getMouseModel();
		Element senderElem = heldPanel.getElement();
		int x = DOM.eventGetClientX(event)
			- DOM.getAbsoluteLeft(senderElem)
			+ Window.getScrollLeft();
		ArrayList colStarts = UIUtil.getAppView().getColStarts();
		int fixed = docModel.getFixedColCount();
		if (x > (Integer)colStarts.get(fixed)) {
			x += viewableLeft;  
		} 
		int col = GridPart.binarySearch(colStarts, 0, colStarts.size(), x, 0);
		CellSelection sel = selectModel.getCurrentSelect();
		sel.rowStart = 0; sel.rowEnd =docModel.getRowCount()-1;
		sel.colStart = mouseModel.getDownCol(); sel.colEnd = col;
		sel.normalize();
		selectModel.fireModelChange();
	}
}
